package com.example.fp.cgc.connerlt

import com.example.fp.cgc.entity.DataState
import com.example.fp.cgc.entity.Tags
import com.example.fp.cgc.mapper.*
import com.example.fp.cgc.util.DataUtil
import com.example.fp.cgc.util.SpringUtil
import com.example.fp.cgc.websocket.WebSocketServer
import com.example.fp.wrt.mapper.LivenessMapper
import com.example.fp.zlz.mapper.AdminMapper
import com.example.fp.zlz.mapper.GameMapper
import com.example.fp.zxd.mapper.GzhMapper
import com.google.gson.Gson
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Lazy
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component

/**
 * 定时器
 * @since 2020-02-20修改
 * @author 蔡
 */
@Component
@EnableScheduling
class AlarmTask {

    companion object {
        val task: AlarmTask by lazy {
            SpringUtil.getBean(AlarmTask::class.java)
        }
    }

    @Autowired
    @Lazy
    lateinit var appsMapper: AppsMapper
    @Autowired
    @Lazy
    lateinit var gameMapper: GameMapper
    @Autowired
    @Lazy
    lateinit var gzhMapper: GzhMapper
    @Autowired
    @Lazy
    lateinit var livenessMapper: LivenessMapper
    @Autowired
    @Lazy
    lateinit var overseasMapper: CgcOverseasMapper
    @Autowired
    @Lazy
    lateinit var adminMapper: AdminMapper
    @Autowired
    @Lazy
    lateinit var messageMapper: MessageMapper

    @Autowired
    @Lazy
    lateinit var dataStateMapper: DataStateMapper
    /**
     * @since 2020-02-26
     */
    @Autowired
    @Lazy
    lateinit var userFollowMapper: UserFollowMapper

    /**
     * @since 2020-02-28
     */
    @Autowired
    @Lazy
    lateinit var userSettingMapper: UserSettingMapper

    data class DataState(
            var time: Long = 0L,
            var data: String = ""
    )

    var dataStateMap = mutableMapOf<String, DataState>()

    var flag = true

    fun init() {
        var list = dataStateMapper.selectList(null)
        if (list.isEmpty()) {
            dataStateMapper.insert(DataState("apps"))
            dataStateMapper.insert(DataState("game"))
            dataStateMapper.insert(DataState("gzh"))
            dataStateMapper.insert(DataState("live"))
            dataStateMapper.insert(DataState("overseas"))
            dataStateMapper.insert(DataState("useronline"))
            list = dataStateMapper.selectList(null)
        }
        list.forEach {
            dataStateMap[it.tname] = DataState(it.time.time, getJSONData(it.tname))
        }
    }

    /**
     * 为主页发送数据
     */
    fun getInitData(): MutableList<String> {
        if (flag) {
            init()
            flag = false
        }

        val dataList = mutableListOf<String>()

        dataStateMap.forEach { (t, _) ->
            dataList.add(getData(t, false))
        }
        return dataList
    }

    /**
     * 应用表定时器
     * 对上一次执行时间之后再执行的时间
     * @throws InterruptedException
     */
    @Scheduled(cron = "0/1 * * * * *")
    @Throws(InterruptedException::class)
    fun appsRun() {
        runData("apps")
    }

    /**
     * 游戏表定时器
     * 对上一次执行时间之后再执行的时间
     * @throws InterruptedException
     */
    @Scheduled(cron = "0/1 * * * * *")
    @Throws(InterruptedException::class)
    fun gameRun() {
        runData("game")
    }

    /**
     * 公众号表定时器
     * 对上一次执行时间之后再执行的时间
     * @throws InterruptedException
     */
    @Scheduled(cron = "0/1 * * * * *")
    @Throws(InterruptedException::class)
    fun gzhRun() {
        runData("gzh")
    }

    /**
     * 应用活跃度表定时器
     * 对上一次执行时间之后再执行的时间
     * @throws InterruptedException
     */
    @Scheduled(cron = "0/1 * * * * *")
    @Throws(InterruptedException::class)
    fun livenessRun() {
        runData("live")
    }

    /**
     * 海外应用表定时器
     * 对上一次执行时间之后再执行的时间
     * @throws InterruptedException
     */
    @Scheduled(cron = "0/1 * * * * *")
    @Throws(InterruptedException::class)
    fun overseasRun() {
        runData("overseas")
    }

    /**
     * 用户登录状态查询定时器
     * 对上一次执行时间之后再执行的时间
     * @throws InterruptedException
     */
    @Scheduled(cron = "0/1 * * * * *")
    @Throws(InterruptedException::class)
    fun userOnlineRun() {
        runData("useronline")
    }

    fun getMessageState(uid: Int): String {
        val readState = messageMapper.getReadState(uid)

        val str =
                """
                    "messageState":${Gson().toJson(readState)},
                """.trimIndent()
        var da = "{"
        da += """
            "type": [{
                "type" : "messageState"
              }],
        """.trimIndent()

        da += str
        da += getJSONData("tokendata")
        da += "}"

        return da
    }

    /**
     * 发送消息数据
     */
    fun sendMessageData(uid: Int, flag: Boolean) {
        var da = ""
        if (flag) {
            da = getMessageState(uid)
        } else {
            da = DataUtil.getUserHistoryList(uid)
        }
        WebSocketServer.onlineUserMap[uid]?.sendMessage(da)
    }

    /**
     * 发送消息盒子数据
     */
    fun sendMessageBox(uid: Int) {
        WebSocketServer.onlineUserMap[uid]?.sendMessage(DataUtil.getMessageBox(uid))
    }

    /**
     * 检测是否发生变化
     */
    fun runData(type: String) {
        if (flag) {
            init()
            flag = false
        }
        Thread.sleep(1000)
        val state = dataStateMapper.selectState(type)

        if (dataStateMap[state.tname]!!.time != state.time.time) {
            dataStateMap[state.tname]!!.time = state.time.time
            WebSocketServer().sendAll(type, getData(type, true))
        }
    }

    /**
     * 获取数据
     */
    fun getData(type: String, flag: Boolean): String {
        var da = "{"
        da += """
            "type": [{
                "type" : "$type"
              }],
        """.trimIndent()
        if (flag) {
            dataStateMap[type]?.data = getJSONData(type)
        }
        da += dataStateMap[type]?.data
        da += getJSONData("tokendata")
        da += "}"
        return da
    }

    /**
     * 获取格式化JSON数据
     */
    fun getJSONData(tableName: String): String {
        return when (tableName) {
            "apps" -> {
                """
                    "app1":${Gson().toJson(getTags())},
                    "app2":${Gson().toJson(appsMapper.getDevelopList())},
                """.trimIndent()
            }
            "gzh" -> {
                """
                    "gzh":${Gson().toJson(gzhMapper.selectTypeList())},
                """.trimIndent()
            }
            "live" -> {
                """
                    "liveness1":${Gson().toJson(livenessMapper.echartzhuxingtu())},
                    "liveness2":${Gson().toJson(livenessMapper.echartbingtu())},
                """.trimIndent()
            }
            "overseas" -> {
                """
                    "oversea":${Gson().toJson(overseasMapper.selectClick())},
                """.trimIndent()
            }
            "game" -> {
                """
                    "gameauthor":${Gson().toJson(gameMapper.selectgameauthor())},
                    "gametypes":${Gson().toJson(gameMapper.selectbytype())},
                """.trimIndent()
            }
            "tokendata" -> {
                """
                    "tokendata":${Gson().toJson(adminMapper.selecttoken())}
                """.trimIndent()
            }
            "useronline" -> {
                """
                    "useronline":${Gson().toJson(adminMapper.selectuseronline())},
                """.trimIndent()
            }

            else -> ""
        }
    }

    /**
     * 获取标签数据
     */
    private fun getTags(): List<Tags> {
        val tagsList = appsMapper.getAppsTags()
        val tagsMap = linkedMapOf<String, Int>()
        tagsList.forEach { tags ->
            val tagList = tags.split(" ")
            tagList.forEach { t ->
                if (tagsMap.containsKey(t)) {
                    val num = tagsMap[t]
                    num?.let {
                        tagsMap[t] = it + 1
                    }
                } else {
                    tagsMap[t] = 1
                }
            }
        }
        return tagsMap.entries.map {
            Tags(it.key, it.value)
        }.sortedBy {
            it.value
        }
    }

}

